<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ttt</title>
    <!-- mapboxgl -->
    <script src="https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.js"></script>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.css" rel="stylesheet" />  

    <!-- echarts -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/echarts@4.6.0/dist/echarts.min.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/echarts-gl@1.1.1/dist/echarts-gl.min.js"></script> -->
    <!-- <script src="echarts.min.385.js"></script> -->
    <!-- <script src="echarts-gl-master.m.js"></script> -->

    <!-- 其他 -->
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <!-- <script src="assets/world.js"></script> -->

    <!-- 百度地图 -->
    <!-- <script src="https://gallerybox.echartsjs.com/dep/echarts/latest/extension/bmap.min.js"></script>
    <script src="https://api.map.baidu.com/api?v=3.0&ak=9Y5hSOZKKo9QcWrwag0qMYYvQ6PIKEzw"></script> -->
    <style>
        body,
        html,
        #map {
            padding: 0;
            margin: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <div id="map" class='map'></div>

    <!-- <script src="echartsopt.js"></script> -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<!-- <script src="three3.js"></script> -->
<script src="https://unpkg.com/three@0.106.2/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="threebox.js"></script>    
  <!-- <script src="mapboxopt.js" type="module"></script> -->
    <!-- <script src="mapboxopt.js"></script> -->
    <script src="mapboxextrude.js"></script>
<!-- <script src="3dmodel.js"></script> -->
<script>
    var __mapcenter__ = [116.582, 35.415];
mapboxgl.accessToken = 'pk.eyJ1IjoiaG91eGlleXUiLCJhIjoiY2pldjE5amU3NndzeDM5bzd5bm9ncDgycyJ9.j1F-Lgid3L5k2Abm8_xTeQ';

var mapboxgl_style = 'mapbox://styles/mapbox/dark-v10';
var tb;
function addTB(mapd, gl) {
    tb = new Threebox(
        mapd,
        gl,
        { defaultLights: true }
    );
    var sphere = tb.sphere({radius:1, color: 'red', material: 'MeshStandardMaterial' })
        .setCoords(__mapcenter__.concat([500]));
    // add sphere to the scene
    tb.add(sphere);
}
const linetype = 0;//0=normal 1=fat
// var map = myChart.getModel().getComponent('mapbox3D').getMapbox();
var map = new mapboxgl.Map({
    container: 'map',
    style: mapboxgl_style,
    zoom: 16,
    center: __mapcenter__,
    pitch: 20,
    antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
});


$.ajaxSettings.async = false;
var linesdata;

// configuration of the custom layer for a 3D model per the CustomLayerInterface
function initThree(_this, mapd) {
    _this.camera = new THREE.Camera();
    _this.scene = new THREE.Scene();
    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
    _this.scene.add(directionalLight);
    _this.map = mapd;
}
var lineGroup;
var mbpt = mapboxgl.MercatorCoordinate.fromLngLat(
    __mapcenter__,
    300
);
var threescale= mbpt.meterInMercatorCoordinateUnits();
function drawLines(scene) {
    lineGroup = new THREE.Group();
    linesdata.features.forEach(function (element, inx) {
        if (element.geometry.coordinates[0] == null) return;
        var basept = lnglatToLocal(element.geometry.coordinates,0);
        var toppt = lnglatToLocal(element.geometry.coordinates,500);
        console.log(basept)
        var lineMesh = drawLine([basept, toppt]);
        lineMesh.scale.set(1, 1, Math.random() * 2);
        lineGroup.add(lineMesh);
    });
    scene.add(lineGroup);
}
var customLayer = {
    id: '3d-model',
    type: 'custom',
    renderingMode: '3d',
    onAdd: function (mapd, gl) {
        initThree(this, mapd);
        addTB(mapd, gl);
        //绘制光源
        addLight(this.scene);
        //绘制飞线
        // drawLines(this.scene);
        //绘制建筑物
        this.drawBuildings();
        this.renderer = new THREE.WebGLRenderer({
            canvas: mapd.getCanvas(),
            antialias: true,
            alpha:true,
            context: gl,
            antialias: true
        });

        this.renderer.autoClear = false;
    },
     drawBuildings(){
        // 把经纬度转换成x,y,z 坐标
        builds.forEach(d => {
          d.vector3 = [];
          d.geometry.coordinates.forEach((coordinates, i) => {
            d.vector3[i] = [];
            coordinates.forEach((c, j) => {
              if (c[0] instanceof Array) {
                d.vector3[i][j] = [];
                c.forEach(cinner => {
                  let cp = lnglatToLocal(cinner,0);
                  d.vector3[i][j].push(cp);
                });
              } else {
                let cp = lnglatToLocal(c,0);
                d.vector3[i].push(cp);
              }
            });
          });
        });
        console.log(builds)
        // 绘制地图模型
        const group = new THREE.Group();
        const lineGroup = new THREE.Group();
        builds.forEach(d => {
          const g = new THREE.Group(); // 用于存放每个地图模块。||省份
          g.data = d;
          d.vector3.forEach(points => {
            // 多个面
            if (points[0][0] instanceof Array) {
              points.forEach(p => {
                if(p.length>3){
                const mesh = drawModel(p);
              //   const lineMesh = drawLine(p);
                // lineGroup.add(lineMesh);
                mesh && g.add(mesh);
                }
              });
            } else {
                if(points[0].length>3){
              // 单个面
              const mesh = drawModel(points[0]);
              // const lineMesh = drawLine(points);
              // lineGroup.add(lineMesh);
              mesh && g.add(mesh);
                }
            }
          });
          group.add(g);
        });
        this.group = group; // 丢到全局去
      //   const lineGroupBottom = lineGroup.clone();
      //   lineGroupBottom.position.z = -2;
      //   this.scene.add(lineGroup);
      //   this.scene.add(lineGroupBottom);
        this.scene.add(group);
  },
    render: function (gl, matrix) {
        // updateLight();
        tb.update();
        // updateLines();
        // console.log(mbpt)
        var m = new THREE.Matrix4().fromArray(matrix);
        var l = new THREE.Matrix4()
        //   .makeTranslation(
        //     mbpt.x,
        //     mbpt.y,
        //     mbpt.z
        //   )
          .scale(
            new THREE.Vector3(
                threescale,
              threescale,
              threescale
            )
          );
        this.camera.projectionMatrix = m.multiply(l);
        this.renderer.state.reset();
        this.renderer.render(this.scene, this.camera);
        this.map.triggerRepaint();
    }
};

map.on('style.load', function () {
    map.addLayer(customLayer);
});
// used to determine the switch point for the light animation
var invert = 1;
var phase = 0;
var pointColor, pointLight, sphereLight, sphereLightMaterial, sphereLightMesh
function addLight(scene) {
    scene.add( new THREE.AmbientLight( 0xffffff ) );
    var sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
    sunlight.position.set(0,80000000,100000000);
    sunlight.matrixWorldNeedsUpdate = true;
    scene.add(sunlight);

    pointColor = "#ccffcc";
    pointLight = new THREE.PointLight(pointColor);
    pointLight.distance = 0.1;
    scene.add(pointLight);
    var pt = mapboxgl.MercatorCoordinate.fromLngLat(
        __mapcenter__,
        600
    );
    var met = pt.meterInMercatorCoordinateUnits();
    // add a small sphere simulating the pointlight
    sphereLight = new THREE.SphereBufferGeometry(30,120,120);
    sphereLightMaterial = new THREE.MeshStandardMaterial({ color: 0xac6c25 });
    sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
    // sphereLightMesh.castShadow = true;
    // sphereLightMesh.position.set(,70,100);

    sphereLightMesh.position.set(pt.x, pt.y, pt.z);
    // sphereLightMesh.scale.set(threescale,threescale,threescale);
    console.log(sphereLightMesh)
    scene.add(sphereLightMesh);
}
/**
  * @desc 经纬度转换成墨卡托投影
  * @param {array} 传入经纬度
  * @return array [x,y,z]
  */
function lnglatToMector(lnglat) {
    var pt = mapboxgl.MercatorCoordinate.fromLngLat(
        lnglat,
        0
    );
    const { x, y, z } = pt;
    return [x, y, z];
}

function drawModel(points) {
    const shape = new THREE.Shape();
    points.forEach((d, i) => {
        const {x, y} = d;
        if (i === 0) {
        shape.moveTo(x, y);
        } else if (i === points.length - 1) {
        shape.quadraticCurveTo(x, y, x, y);
        } else {
        shape.lineTo(x, y, x, y);
        }
    });

    const geometry = new THREE.ExtrudeGeometry(shape, {
        depth: -2,
        bevelEnabled: false
    });
    const material = new THREE.MeshBasicMaterial({
        color: 'red',
        transparent: false,
        opacity: 0.6,
        side: THREE.DoubleSide
    });
    const mesh = new THREE.Mesh(geometry, material);
    return mesh;
}
</script>
</body>

</html>